#define _WIN32_WINNT 0x0500

#include <windows.h> 
#include <tchar.h>
#include <detours.h>
#include <iostream>
#include <crtdbg.h>
#include "d3d9/d3d9.h"

#define _CRTDBG_MAP_ALLOC

#ifdef _DEBUG
#define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
#define new DEBUG_NEW
#endif

HANDLE HookHandle = NULL;
static IDirect3D9* (WINAPI* Direct3DCreate9Next)(UINT SDKVersion) = Direct3DCreate9;

IDirect3D9* Direct3D;
IDirect3D9* Mine_Direct3D;

IDirect3D9* WINAPI Mine_Direct3DCreate9(UINT SDKVersion) 
{ 
	Direct3D      = Direct3DCreate9Next( SDKVersion ); 
	Mine_Direct3D   = new hkIDirect3D9( &Direct3D ); 
	return Mine_Direct3D; 
}

void HookAPI() 
{ 
	long returnvalue;

	DetourTransactionBegin();
	DetourUpdateThread(GetCurrentThread());
	returnvalue = DetourAttach((PVOID*)&Direct3DCreate9Next, Mine_Direct3DCreate9);
	if (returnvalue != NO_ERROR) {
		Utils::Log(LOGFILE, "Failed to attach D3D device\n");
	}
	DetourTransactionCommit();
}

void UnhookAPI() 
{ 
	DetourDetach((PVOID*)Direct3DCreate9Next, (PVOID*)Mine_Direct3DCreate9);
	delete(Direct3D);
	delete(Mine_Direct3D);
}

BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) 
{ 
#ifdef _DEBUG
	HANDLE hLogFile = CreateFile("xenergy\\LeakLog.txt", GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
#endif
	if (ul_reason_for_call == DLL_PROCESS_ATTACH) 
	{ 
#ifdef _DEBUG
		_CrtSetReportMode(_CRT_WARN | _CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
		_CrtSetReportFile(_CRT_WARN | _CRT_ERROR, hLogFile);
		_RPT0(_CRT_WARN,"file message\n");


		_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
#endif

		DisableThreadLibraryCalls(hModule); 
		HookHandle = hModule; 
		HookAPI(); 
	} 
	else if (ul_reason_for_call == DLL_PROCESS_DETACH) 
	{ 
#ifdef _DEBUG
		CloseHandle(hLogFile);
#endif
		UnhookAPI(); 
	} 
	return TRUE; 
}